#include <cppunit/config/SourcePrefix.h>
#include "TestQueryPreprocessor.h"
#include <string>

using namespace std;

void TestQueryPreprocessor::setUp() {
}

void TestQueryPreprocessor::tearDown() {
}

CPPUNIT_TEST_SUITE_REGISTRATION( TestQueryPreprocessor );

void TestQueryPreprocessor::testBuildQuery(){
	string query1 = "assign a; Select a such that Modifies(a,\"x\")"; //valid
	string query2 = "while w; Select w such that Modifies(w,\"x\")"; //valid
	string query3 = "assign a; Select a such that Modifies(a1,\"x\")"; //invalid
	string query4 = "assign a, a1; Select a such that Modifies(a,\"x\") pattern a1(_,_)"; //valid
	string query5 = "assign a; while w; Select a such that Modifies(a,\"x\") pattern w(_,_)"; //invalid
	string query6 = "assignn a; Select a"; //syntax invalid

	int numParams, numQueries;

	QueryPreprocessor qp1 = QueryPreprocessor(query1);
	CompleteQuery *cq1 = qp1.buildQuery();
	numParams = cq1->getDeclarationParameters().size();
	numQueries = cq1->getSuchThatQuery().size() + cq1->getPatternQuery().size();
	CPPUNIT_ASSERT_EQUAL_MESSAGE("One Query", 1, numQueries);
	CPPUNIT_ASSERT_EQUAL_MESSAGE("Two parameters", 2, numParams);
	CPPUNIT_ASSERT_EQUAL_MESSAGE("Result", string("a"), cq1->getResult()->getVariable());

	QueryPreprocessor qp2 = QueryPreprocessor(query2);
	CompleteQuery *cq2 = qp2.buildQuery();
	numParams = cq2->getDeclarationParameters().size();
	numQueries = cq2->getSuchThatQuery().size() + cq2->getPatternQuery().size();
	CPPUNIT_ASSERT_EQUAL_MESSAGE("One Query", 1, numQueries);
	CPPUNIT_ASSERT_EQUAL_MESSAGE("Two parameters", 2, numParams);
	CPPUNIT_ASSERT_EQUAL_MESSAGE("Result", string("w"), cq2->getResult()->getVariable());

	bool exceptionThrown = false;
	QueryPreprocessor qp3 = QueryPreprocessor(query3);
	try{
		CompleteQuery *cq3 = qp3.buildQuery();
	} catch(CustomException e){
		exceptionThrown = true;
	}

	CPPUNIT_ASSERT_EQUAL_MESSAGE("exception caught", true, exceptionThrown);

	QueryPreprocessor qp4 = QueryPreprocessor(query4);
	CompleteQuery *cq4 = qp4.buildQuery();
	numParams = cq4->getDeclarationParameters().size();
	numQueries = cq4->getSuchThatQuery().size() + cq4->getPatternQuery().size();
	CPPUNIT_ASSERT_EQUAL_MESSAGE("Two Query", 2, numQueries);
	CPPUNIT_ASSERT_EQUAL_MESSAGE("Three parameters", 3, numParams);
	CPPUNIT_ASSERT_EQUAL_MESSAGE("Result", string("a"), cq1->getResult()->getVariable());


	exceptionThrown = false;
	QueryPreprocessor qp5 = QueryPreprocessor(query5);
	try{
		CompleteQuery *cq5 = qp5.buildQuery();
	} catch (CustomException e){
		exceptionThrown = true;
	}
	CPPUNIT_ASSERT_EQUAL_MESSAGE("Query semantically invalid", true, exceptionThrown);

	exceptionThrown = false;
	try{
		QueryPreprocessor qp = QueryPreprocessor(query6);
	} catch (CustomException e){
		exceptionThrown = true;
	}
	CPPUNIT_ASSERT_EQUAL_MESSAGE("Query syntactically invalid", true, exceptionThrown);
}